/**
 * 
 */
package DB;

import gui.LoaderGif;

import java.util.List;

import main.Session;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Region;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.wb.swt.SWTResourceManager;

import Utils.Concurrent.AsyncTask;
import Utils.Concurrent.LoaderRunner;
import Utils.Concurrent.ThreadTasks.AddPersonTask;
import Utils.Concurrent.ThreadTasks.GetMediaTask;
import Utils.Concurrent.ThreadTasks.SearchTask;
import Utils.UI.UIUpdater;

import datatype.DBtypes.FilmfromDB;
import datatype.DBtypes.ProgramfromDB;
import datatype.searchtype.SearchResult;
import datatype.searchtype.SearchResult.MediaRes;
import datatype.searchtype.SearchResult.PersonRes;

/**
 * @author Yuval
 * 
 *         -------------------- information -------------------------
 *         - this class handle all the search section				-
 *         - in the application, from the 							-
 *         - the functions mostly handle the gui, 					- 
 *         - if by modify it, or add the listeners					 -
 *         ----------------------------------------------------------
 */
public class SearchDB {

	private Text searchTXT;
	private Button goBTN;
	private Table programTBL, filmTBL, actorTBL, creatorTBL, directorTBL;
	private Button programCHK, filmCHK, actorCHK, creatorCHK, diractorCHK,
			createFilm, createProgram, createActor, createCreator,
			createDirector, returnBTN;
	private Composite editTV, editFilm, searchENG_addPerson;
	private Canvas searchLoading;

	private SearchResult searchResults;
	private Label lblFirstName;
	private Text addPerson_firstNameTXT;
	private Text addPerson_lastNameTXT;
	private Button btnCancel;
	private Button btnAddPerson;
	private Canvas loading;

	private Button[] buttons;
	private SearchTask searchTask = null;

	private String personType = "";

	public synchronized SearchResult getSearchResults() {
		return searchResults;
	}

	public synchronized void setSearchResults(SearchResult searchResults) {
		this.searchResults = searchResults;
	}

	public SearchDB(Text searchTXT, Button goBTN, Table programTBL,
			Table filmTBL, Table actorTBL, Table creatorTBL, Table directorTBL,
			Button programCHK, Button filmCHK, Button actorCHK,
			Button creatorCHK, Button diractorCHK, Composite editTV,
			Composite editFilm, Button createFilm, Button createProgram,
			Button createActor, Button createCreator, Button createDirector,
			Composite searchENG_addPerson, Button returnBTN,
			Canvas searchLoading) {
		super();
		this.searchTXT = searchTXT;
		this.goBTN = goBTN;
		this.programTBL = programTBL;
		this.filmTBL = filmTBL;
		this.actorTBL = actorTBL;
		this.creatorTBL = creatorTBL;
		this.directorTBL = directorTBL;
		this.programCHK = programCHK;
		this.filmCHK = filmCHK;
		this.actorCHK = actorCHK;
		this.creatorCHK = creatorCHK;
		this.diractorCHK = diractorCHK;
		this.editFilm = editFilm;
		this.editTV = editTV;
		this.createFilm = createFilm;
		this.createProgram = createProgram;
		this.createActor = createActor;
		this.createCreator = createCreator;
		this.createDirector = createDirector;
		this.searchENG_addPerson = searchENG_addPerson;
		this.returnBTN = returnBTN;
		this.searchLoading = searchLoading;

		buttons = new Button[] { createFilm, createProgram, createActor,
				createCreator, createDirector, returnBTN, goBTN };
		prepareAllWidgets();

	}

	/*
	 * set the listener for the widgets, every widgets that need to connect to
	 * the server, create new task, each one has it own task in the threadTask
	 * class
	 */
	private void prepareAllWidgets() {

		prepareAddPersonWindow();

		goBTN.addMouseListener(new MouseAdapter() {
			LoaderGif lg;

			@Override
			public void mouseDown(MouseEvent arg0) {
				if (lg == null)
					lg = new LoaderGif(searchLoading, 4);

				if (searchTask != null) {
					Session.pool.killAll(searchTask, lg.getLoaderTask());
					Session.poolForSearch.killAll();

				}

				boolean[] whatToSearch = { filmCHK.getSelection(),
						programCHK.getSelection(), actorCHK.getSelection(),
						creatorCHK.getSelection(), diractorCHK.getSelection() };

				boolean isNeedToSearch = false;
				for (boolean b : whatToSearch)
					isNeedToSearch = isNeedToSearch || b;
				isNeedToSearch = isNeedToSearch
						&& !searchTXT.getText().equals("");

				if (isNeedToSearch) {
					searchTask = new SearchTask(Session.gui.getDisplay(),
							whatToSearch, searchTXT.getText(), lg);

					for (Button b : buttons)
						b.setEnabled(false);
					lg.showLoader();
					Session.pool.pushUrgentTask(searchTask, lg.getLoaderTask());
				}
			}

		});

		programTBL.addMouseListener(new MouseAdapter() {

			GetMediaTask getProgramTask = null;

			@Override
			public void mouseDoubleClick(MouseEvent arg0) {
				int selection = programTBL.getSelectionIndex();

				if (selection >= 0) {

					if (getProgramTask != null)
						Session.pool.killAll(getProgramTask);

					getProgramTask = new GetMediaTask(Session.gui.getDisplay(),
							searchResults.getProgramRes().get(selection)
									.getId(), "program", editTV);

					Session.pool.addTaskToPool(true, getProgramTask);
					resetSearchTXT();
					programTBL.setFocus();
				}
			}

		});

		filmTBL.addMouseListener(new MouseAdapter() {

			GetMediaTask getFilmTask = null;

			@Override
			public void mouseDoubleClick(MouseEvent arg0) {
				int selection = filmTBL.getSelectionIndex();

				if (selection >= 0) {

					if (getFilmTask != null)
						Session.pool.killAll(getFilmTask);

					getFilmTask = new GetMediaTask(Session.gui.getDisplay(),
							searchResults.getFilmRes().get(selection).getId(),
							"film", editFilm);

					Session.pool.addTaskToPool(true, getFilmTask);
					resetSearchTXT();
					filmTBL.setFocus();
				}
			}
		});

		createProgram.addMouseListener(new MouseAdapter() {

			@Override
			public void mouseDown(MouseEvent arg0) {
				Session.gui.changeScreenTo(editTV);
				Session.gui.getEditProgram().setProgram(new ProgramfromDB());

				resetSearchTXT();
				createProgram.setFocus();
			}

		});

		createFilm.addMouseListener(new MouseAdapter() {

			@Override
			public void mouseDown(MouseEvent arg0) {
				Session.gui.changeScreenTo(editFilm);
				Session.gui.getEditFilm().setFilm(new FilmfromDB());
				resetSearchTXT();
				createFilm.setFocus();
			}

		});

		createActor.addMouseListener(new MouseAdapter() {

			@Override
			public void mouseDown(MouseEvent arg0) {
				setVisibilty(true);
				loading.setVisible(false);
				personType = "actor";
			}
		});

		createCreator.addMouseListener(new MouseAdapter() {

			@Override
			public void mouseDown(MouseEvent arg0) {
				setVisibilty(true);
				loading.setVisible(false);
				personType = "creator";
			}
		});
		createDirector.addMouseListener(new MouseAdapter() {

			@Override
			public void mouseDown(MouseEvent arg0) {
				setVisibilty(true);
				loading.setVisible(false);
				personType = "director";
			}
		});

		btnCancel.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseDown(MouseEvent arg0) {
				setVisibilty(false);
				addPerson_firstNameTXT.setText("");
				addPerson_lastNameTXT.setText("");
				filmTBL.setFocus();
			}
		});

		btnAddPerson.addMouseListener(new MouseAdapter() {

			AddPersonTask addPersonTask = null;
			LoaderGif lg;

			@Override
			public void mouseDown(MouseEvent arg0) {
				if (lg == null)
					lg = new LoaderGif(loading, 1);

				if (addPersonTask != null)
					Session.pool.killAll(addPersonTask);

				if (!addPerson_firstNameTXT.getText().equals("")) {
					addPersonTask = new AddPersonTask(Session.gui.getDisplay(),
							personType, addPerson_firstNameTXT.getText(),
							addPerson_lastNameTXT.getText(), lg);
					btnCancel.setEnabled(false);
					btnAddPerson.setEnabled(false);
					lg.showLoader();
					Session.pool.pushUrgentTask(addPersonTask,
							lg.getLoaderTask());
				}

			}
		});

		returnBTN.addMouseListener(new MouseAdapter() {

			@Override
			public void mouseDown(MouseEvent arg0) {
				if (searchTask != null)
					Session.pool.killAll(searchTask);
				Session.gui.changeScreenTo(Session.gui.getMainScreen());
				clearSearch();
			}

		});

	}

	/*
	 * after the search in the DB finished, the thread that handled the search
	 * invokes this function, using a special function in the UIUpdater class
	 * the function put the results in the tables
	 */
	public void updateTables() {
		programTBL.removeAll();
		filmTBL.removeAll();
		actorTBL.removeAll();
		creatorTBL.removeAll();
		directorTBL.removeAll();

		if (searchResults.getFilmRes() != null)
			setTableM(filmTBL, searchResults.getFilmRes());
		if (searchResults.getProgramRes() != null)
			setTableM(programTBL, searchResults.getProgramRes());
		if (searchResults.getActorRes() != null)
			setTableP(actorTBL, searchResults.getActorRes());
		if (searchResults.getCreatorRes() != null)
			setTableP(creatorTBL, searchResults.getCreatorRes());
		if (searchResults.getDirectorRes() != null)
			setTableP(directorTBL, searchResults.getDirectorRes());

		for (Button b : buttons)
			b.setEnabled(true);

	}
	/*
	 * do the actual update of the table
	 */
	private void setTableM(Table table, List<MediaRes> resLst) {
		for (MediaRes mr : resLst) {
			TableItem ti = new TableItem(table, SWT.NONE);
			ti.setText(0, mr.getName());
			ti.setText(1, "" + mr.getReleaseYear());
		}

	}
	/*
	 * do the actual update of the table
	 */
	private void setTableP(Table table, List<PersonRes> resLst) {
		for (PersonRes pr : resLst) {
			TableItem ti = new TableItem(table, SWT.NONE);
			ti.setText(0, pr.getName());
			ti.setText(1, pr.getKnownFor());
		}

	}

	private void resetSearchTXT() {
		searchTXT.setText("");
	}

	private void clearSearch() {
		searchTXT.setText("");
		actorTBL.removeAll();
		creatorTBL.removeAll();
		directorTBL.removeAll();
		filmTBL.removeAll();
		programTBL.removeAll();
		filmCHK.setSelection(true);
		programCHK.setSelection(true);
		actorCHK.setSelection(true);
		creatorCHK.setSelection(true);
		diractorCHK.setSelection(true);

	}

	private void prepareAddPersonWindow() {

		lblFirstName = new Label(searchENG_addPerson, SWT.NONE);
		lblFirstName.setBackground(SWTResourceManager
				.getColor(SWT.COLOR_DARK_GRAY));
		lblFirstName.setFont(SWTResourceManager.getFont("Segoe UI", 13,
				SWT.NORMAL));
		lblFirstName.setBounds(10, 14, 120, 37);
		lblFirstName.setText("first Name:");

		addPerson_firstNameTXT = new Text(searchENG_addPerson, SWT.BORDER);
		addPerson_firstNameTXT.setFont(SWTResourceManager.getFont("Segoe UI",
				11, SWT.NORMAL));
		addPerson_firstNameTXT.setMessage("type the first name");
		addPerson_firstNameTXT.setBounds(130, 15, 180, 37);
		addPerson_firstNameTXT.setTextLimit(100);

		Label lblLastName = new Label(searchENG_addPerson, SWT.NONE);
		lblLastName.setBackground(SWTResourceManager
				.getColor(SWT.COLOR_DARK_GRAY));
		lblLastName.setText("last Name:");
		lblLastName.setFont(SWTResourceManager.getFont("Segoe UI", 13,
				SWT.NORMAL));
		lblLastName.setBounds(10, 57, 120, 37);

		addPerson_lastNameTXT = new Text(searchENG_addPerson, SWT.BORDER);
		addPerson_lastNameTXT.setMessage("type the last name");
		addPerson_lastNameTXT.setFont(SWTResourceManager.getFont("Segoe UI",
				11, SWT.NORMAL));
		addPerson_lastNameTXT.setBounds(130, 58, 180, 37);
		addPerson_lastNameTXT.setTextLimit(100);
		btnCancel = new Button(searchENG_addPerson, SWT.NONE);
		btnCancel.setBounds(10, 100, 90, 30);
		btnCancel.setText("cancel");

		btnAddPerson = new Button(searchENG_addPerson, SWT.NONE);
		btnAddPerson.setBounds(219, 101, 90, 30);
		btnAddPerson.setText("add Person");

		loading = new Canvas(searchENG_addPerson, SWT.NONE);
		loading.setVisible(false);
		loading.setBounds(144, 99, 32, 32);
		setVisibilty(false);

	}

	private void setVisibilty(boolean visi) {

		for (Control c : searchENG_addPerson.getChildren()) {
			c.setVisible(visi);
		}
		for (Button b : buttons)
			b.setEnabled(!visi);

		searchENG_addPerson.setVisible(visi);

	}

	public void clearAddWindow() {
		setVisibilty(false);
		addPerson_firstNameTXT.setText("");
		addPerson_lastNameTXT.setText("");
		filmTBL.setFocus();
		btnCancel.setEnabled(true);
		btnAddPerson.setEnabled(true);
	}
}
